<?php

namespace App\Kuafu\Category\Service;

use App\Exceptions\BaseException;
use App\Kuafu\Category\Enum\CategoryCacheEnum;
use App\Kuafu\Category\Enum\CategoryCodeEnum;
use App\Kuafu\Category\Exceptions\CategoryException;
use App\Kuafu\Category\Model\CategoryModel;
use App\Kuafu\Config\Service\ConfigService;
use App\Kuafu\Product\Enum\CodeEnum;
use App\Kuafu\ProductMenu\Model\ProductMenu;
use App\Kuafu\User\Service\AuthService;
use Illuminate\Support\Facades\Cache;
use App\Kuafu\Base\Service\BaseService;

class CategoryService extends BaseService
{

    /**
     * insert
     * @param $request
     * @throws CategoryException
     */
    public static function addCategory($request)
    {
        try {
            $brandId   = $request->header('brandId');
            $data      = [
                'brandId'  => $brandId,
                'name'     => $request->name,
                'desc'     => '',
                'imageUrl' => '',
                'sort'     => $request->sort,
                'menuId'   => 0,
                'pid'      => 0,
            ];
            $pCategory = CategoryModel::addData($data);

            $menuIds = ProductMenu::query()->pluck('id');
            $addData = [];
            foreach ($menuIds as $menuId) {
                $data['pid']       = $pCategory->id;
                $data['menuId']    = $menuId;
                $data['createdAt'] = $data['updatedAt'] = time();

                $addData[] = $data;
            }
            CategoryModel::insert($addData);

            Cache::forget(CategoryCacheEnum::getCategoryList($brandId, 0));
        } catch (\Throwable $exception) {
            throw new CategoryException(
                CategoryCodeEnum::ERR_INSERT_ERROR,
                CategoryCodeEnum::CODE_TEXT[CategoryCodeEnum::ERR_INSERT_ERROR],
                $exception
            );
        }
    }

    /**
     * 批量新增菜单下的分类
     * @param int $brandId
     * @param int $menuId
     * @param array $categoryList
     * @throws CategoryException
     */
    public static function batchAddCategory(int $brandId, int $menuId, array $categoryList)
    {
        $categoryList = array_column($categoryList, null, 'categoryId');

        $insertAdd = CategoryService::getCategoryList($brandId, 0)->map(function ($item) use ($categoryList, $menuId) {
            $item['name']      = $categoryList[$item['id']]['name'] ?? $item['name'];
            $item['menuId']    = $menuId;
            $item['createdAt'] = $item['updatedAt'] = time();

            $cId  = $categoryList[$item['id']]['categoryId'] ?? 0;
            $cate = CategoryModel::query()->where('id', $cId)->first();
            if ($cate->pid == 0) {
                $item['pid'] = $cate->id;
            } else {
                $item['pid'] = $cate->pid;
            }

            try {
                $operateId = AuthService::getUserId();
            } catch (\Exception $e) {
                $operateId = 0;
            }

            $item['createdByUid'] = $item['updatedByUid'] = $operateId;
            unset($item['id']);

            $item->timestamps = false;
            return $item;
        })->toArray();

        CategoryModel::addDataBatch($insertAdd);

        Cache::forget(CategoryCacheEnum::getCategoryList($brandId, $menuId));
    }

    /**
     * 批量复制菜单下的分类
     * @param int $brandId
     * @param int $menuId
     * @param array $categoryList
     * @throws CategoryException
     */
    public static function batchCopyCategory(int $brandId, int $menuId, array $categoryList)
    {
        // 不是父级分类ids
        $categoryList = array_column($categoryList, null, 'categoryId');


        $categoryIds = array_column($categoryList, 'categoryId');
        $insertAdd   = CategoryModel::query()
                                    ->whereIn('id', $categoryIds)
                                    ->get()
                                    ->keyBy('id')
                                    ->map(function ($item) use ($menuId, $categoryList) {
                                        $item['name']      = $categoryList[$item['id']]['name'] ?? $item['name'];
                                        $item['menuId']    = $menuId;
                                        $item['createdAt'] = $item['updatedAt'] = time();

                                        try {
                                            $operateId = AuthService::getUserId();
                                        } catch (\Exception $e) {
                                            $operateId = 0;
                                        }

                                        $item['createdByUid'] = $item['updatedByUid'] = $operateId;
                                        unset($item['id']);

                                        $item->timestamps = false;
                                        return $item;
                                    })->toArray();

        CategoryModel::addDataBatch($insertAdd);

        Cache::forget(CategoryCacheEnum::getCategoryList($brandId, $menuId));
    }

    /**
     * 批量编辑菜单下的分类
     * @param int $brandId
     * @param int $menuId
     * @param array $categoryList
     */
    public static function batchEditCategory(int $brandId, int $menuId, array $categoryList)
    {
        $categoryList = array_column($categoryList, null, 'categoryId');
        $categoryIds  = array_column($categoryList, "categoryId");

        $sort = 1;
        CategoryService::getCategoryList($brandId, $menuId)->each(function ($item) use ($categoryList, $menuId, &$sort, $categoryIds) {
            $item['name']      = $categoryList[$item['id']]['name'] ?? $item['name'];
            $item['sort']      = ((int)array_search($item->id, $categoryIds)) + 1;
            $item['updatedAt'] = time();

            try {
                $operateId = AuthService::getUserId();
            } catch (\Exception $e) {
                $operateId = 0;
            }

            $item['updatedByUid'] = $operateId;

            CategoryModel::setCategoryInfoById($item['id'], $item->toArray());
            $sort++;
        });

        Cache::forget(CategoryCacheEnum::getCategoryList($brandId, $menuId));
    }

    /**
     * 获取分类列表 - 带缓存
     * @param int $brandId
     * @param int $menuId
     * @param array|string[] $selectColumn
     * @return mixed
     */
    public static function getCategoryList(
        int $brandId,
        int $menuId = 0,
        array $selectColumn = ['*'],
        int $needCategory = 0
    ) {
        $list = Cache::remember(CategoryCacheEnum::getCategoryList($brandId, $menuId) . $needCategory, 10,
            function () use ($brandId, $menuId, $needCategory) {
                return CategoryModel::getListByBrandId($brandId, $menuId, ['*'], $needCategory);
            });

        // 上线容错处理，menuId拿不到自己的，就取0
        if ($menuId != 0 && $list->count() == 0) {
            return self::getCategoryList($brandId, 0, $selectColumn);
        }

        if ($selectColumn == ['*']) {
            return $list;
        }

        // 处理$select
        return $list->map(function ($item) use ($selectColumn) {
            $r = [];
            foreach ($selectColumn as $column) {
                $r[$column] = $item->$column;
            }

            return $r;
        });
    }

    /**
     * 过滤没有分类的菜品分类列表
     * @param $brandId
     * @param $menuId
     * @param $field
     * @param $oriList
     * @param $productList
     * @param int $needCategory
     * @return array
     * @throws BaseException
     */
    public static function filterNoProductCategory($brandId, $menuId, $field, $oriList, $productList,int $needCategory = 0): array
    {
        // todo 获取门店赠品菜单分类id
        $menuGiftCategory = ConfigService::getConfigDetail("menu", "giftCategory")["value"];

        $categoryList = CategoryService::getCategoryList($brandId, $menuId, ['id', 'name', 'pid', 'sort'], $needCategory)
                                       ->filter(function ($item) use ($oriList, &$productList) {
                                           // 过滤掉没有商品的分类
                                           $hitCategory = false;

                                           foreach ($oriList as $p) {
                                               if ($p['kind'] == CodeEnum::KIND_NORMAL) {
                                                   if ($p['categoryId'] == $item['id']) {
                                                       $productList[] = $p;
                                                       $hitCategory   = true;
                                                   }
                                               } else {
                                                   if ($p['type'] == CodeEnum::PRODUCT_TYPE_PACKAGE) {
                                                       $item['pid'] = $item['id'];
                                                   }

                                                   if ($p['categoryId'] == $item['pid']) {
                                                       $p['categoryId'] = $item['id'];
                                                       $productList[]   = $p;
                                                       $hitCategory     = true;
                                                   }
                                               }
                                           }
                                           return $hitCategory;
                                       })->values();
        return [
            'categoryList' => $categoryList->map(function ($item)use($menuGiftCategory) {
                if(in_array($item["pid"], $menuGiftCategory)){
                    $item["isGiftCategory"] = true;
                }else{
                    $item["isGiftCategory"] = false;
                }
                return $item;
            }),
            'productList'  => $productList
        ];
    }

    /**
     * get info
     * @param $request
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public static function getCategoryInfo($request)
    {
        return CategoryModel::getCategoryInfoById($request->categoryId);
    }

    /**
     * update category
     * @param $request
     * @throws CategoryException
     */
    public static function setCategory($request)
    {
        $data = [
            'name'      => $request->name,
            'desc'      => '',
            'imageUrl'  => '',
            'sort'      => $request->sort,
            'updatedAt' => time()
        ];
        $id   = CategoryModel::setCategoryInfoById($request->categoryId, $data);
        if (!$id) {
            throw new CategoryException(
                CategoryCodeEnum::ERR_UPDATE_ERROR,
                CategoryCodeEnum::CODE_TEXT[CategoryCodeEnum::ERR_UPDATE_ERROR]
            );
        }

        Cache::forget(CategoryCacheEnum::getCategoryList($request->header('brandId'), 0));
    }


    /**
     * delete category
     * @param $request
     * @throws CategoryException
     */
    public static function deleteCategory($request)
    {
        $id = CategoryModel::setCateGoryColumnById($request->categoryId, 'isDeleted', 1);
        if (!$id) {
            throw new CategoryException(
                CategoryCodeEnum::ERR_UPDATE_ERROR,
                CategoryCodeEnum::CODE_TEXT[CategoryCodeEnum::ERR_UPDATE_ERROR]
            );
        }

        Cache::forget(CategoryCacheEnum::getCategoryList($request->header('brandId'), 0));
    }

    public static function getCateListByIds($cateIds)
    {
        return CategoryModel::getCateListByIds($cateIds);
    }

    /**
     * 根据pid查询菜单下的categoryId
     * @param int $pid
     * @param int $menuId
     * @return int
     */
    public static function getMenuCategoryIdByPid(int $pid, int $menuId): int
    {
        // 查该菜品的新分类信息
        $category = CategoryModel::query()
                                 ->where('pid', $pid)
                                 ->where('menuId', $menuId)
                                 ->select('id')
                                 ->first();
        if ($category) {
            return (int)$category->id;
        }

        // 建一个
        $oriCategory = CategoryModel::query()
                                    ->where('id', $pid)
                                    ->first();
        if ($oriCategory) {
            $oriCategory              = $oriCategory->toArray();
            $oriCategory['pid']       = $oriCategory['id'];
            $oriCategory['createdAt'] = $oriCategory['updatedAt'] = time();
            $oriCategory['menuId']    = $menuId;
            unset($oriCategory['id']);

            return (int)CategoryModel::query()->insertGetId($oriCategory);
        }

        return 0;
    }
}
